package config;

import com.alibaba.druid.pool.DruidDataSource;
import com.dao.impl.DbConfig;
import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.sql.DataSource;
import java.util.Properties;

/**
 * MapperScan注解会扫描dao的所有接口，并生成一个代理类
 * 里面的代码类似下面这样，此类会被注册到spring容器中
 * 这样其它地方就可以自动注入Mapper接口了
 * <p>
 * SqlSessionFactory factory;
 * SqlSession session = factory.getSession(true);
 * <p>
 * EmpMapper mapper = session.getMapper(EmpMapper.class);
 * <p>
 * mapper.get
 */
@Configuration
@EnableWebMvc
//与mapperScan都扫描了com.dao 有问题吗？没问题
@ComponentScan("com")
@PropertySource("classpath:db.properties")
//此注解来自于mybatis-spring用来扫描所有的mapper接口
@MapperScan("com.dao")
@EnableTransactionManagement
public class AppConfig implements WebMvcConfigurer {

    @Autowired
    private DbConfig dbConfig;
    // mybatis-config.xml(连接用，添加mappers.xml文件)
    // mapper文件，写sql语句
    // SqlSessionFactory ----> SqlSession --->getMapper(XX.class)--->crud

    /**
     * classpath: 在当前项目的类路径下找资源，见ResourceLoader接口中的源码注释
     * classpath*： 在当前项目的类路径下以及部署的所有jar的根下找资源，
     * 见ResourcePatternResolver接口中的源码注释
     *
     * @return
     * @throws Exception
     */
    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource());
        // 方法一：直接使用资源类
        // ClassPathResource resource = new ClassPathResource("mappers/empmapper.xml");
        // PathMatchingResourcePatternResolver 支持ant地址格式

        //方法二（推荐使用）：利用资源加载器（ResourceLoader），因为其支持ant地址，功能更强
        PathMatchingResourcePatternResolver loader = new PathMatchingResourcePatternResolver();
        //一定要记得调用的是getResources方法而不是getResource方法，
        // getResource方法会采用默认加载器（DefaultResourceLoader），不支持classpath*前缀以及ant地址格式
        Resource[] resource = loader.getResources("classpath*:mappers/**/*.xml");

        factoryBean.setMapperLocations(resource);

        PageInterceptor pageInterceptor = pageInterceptor();
        factoryBean.setPlugins(pageInterceptor);
        //实体类的别名
        factoryBean.setTypeAliasesPackage("com.entity");
        //配置很多的自定义配置，当前主要下划线和日志
        factoryBean.setConfiguration(configuration());
        return factoryBean.getObject();
    }

    private org.apache.ibatis.session.Configuration configuration() {
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        //配置是可以把emp_name映射为empName
        configuration.setMapUnderscoreToCamelCase(true);
        //配置日志
        configuration.setLogImpl(StdOutImpl.class);
        return configuration;
    }

    //不需要给此方法添加@Bean注解，没有必要
    private PageInterceptor pageInterceptor() {
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties properties = new Properties();
        properties.setProperty("supportMethodsArguments", "true");
        properties.setProperty("reasonable", "true");
        properties.setProperty("helperDialect", "mysql");
        pageInterceptor.setProperties(properties);
        return pageInterceptor;

    }

    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(dbConfig.getUrl());
        dataSource.setUsername(dbConfig.getUsername());
        dataSource.setPassword(dbConfig.getPassword());
        dataSource.setDriverClassName(dbConfig.getDriverClassName());
        return dataSource;
    }


    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/", ".jsp");
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource());
        return transactionManager;
    }
}
